#include <GLES3/gl3.h>
#include <GLFW/glfw3.h>
#include <cmath>
#include <iostream>

#include <render/output/OGLRender.h>
#include <mesh/mesh.h>
#include <app/Atime.h>
#include <app/Application.h>

enum {
    POSITION_VB,
    NUM_BUFFERS
};

void OGLRender::mainCycle () {
    //if using GLFW
    if ( (*app).openGLTools.OpenGLContext == OGLC_GLFW ) {
        
        while ( !window -> isClosed () ) {
            glfwPollEvents ();
            glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

            (*app).update ();

            window -> Update(); 
        }
        
    //if using Qt tools
    } else if ( (*app).openGLTools.OpenGLContext == OGLC_GLFW ) {
        
        while ( !(*app).openGLTools.glWindowShouldClose ) {
            glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
            
            (*app).update ();
            
            (*app).openGLTools.glSwapBuffers ();
        }
    }
}

void OGLRender::joinToMainCycle () {
    mainCycle ();
}

OGLRender::OGLRender ( Application* appPtr, Window* win ) {
    app = appPtr;
    window = win;
}

void OGLRender::Draw( Mesh& mesh ) {
    unsigned int VAO; //vertex array object
    unsigned int VBO [2]; //vertex buffer object
    unsigned int drawCount;
    
    enum {
        POSITION_VB, TEXTURE_VB
    };
    
    drawCount = mesh.viewPoints.size ();
    
    glGenVertexArrays ( 1, &VAO );
    glBindVertexArray ( VAO );
    
    glGenBuffers ( 1, &VBO [ POSITION_VB ] );
    glBindBuffer ( GL_ARRAY_BUFFER, VBO [ POSITION_VB ] );
    glBufferData ( GL_ARRAY_BUFFER, drawCount * sizeof ( mesh.viewPoints [0] ), mesh.viewPoints.data (), GL_DYNAMIC_DRAW );
    
    glEnableVertexAttribArray ( 0 );
    glVertexAttribPointer ( 0, 3, GL_DOUBLE, GL_FALSE, 0, 0 );
    glEnableVertexAttribArray ( 0 );
    
    
    glGenBuffers ( 1, &VBO [ TEXTURE_VB ] );
    glBindBuffer ( GL_ARRAY_BUFFER, VBO [ TEXTURE_VB ] );
    glBufferData ( GL_ARRAY_BUFFER, drawCount * sizeof ( mesh.textureCoordinate [0] ), 
                   &mesh.textureCoordinate [0], GL_DYNAMIC_DRAW );
    
    glEnableVertexAttribArray ( 1 );
    glVertexAttribPointer ( 0, 2, GL_DOUBLE, GL_FALSE, 0, 0 );
    glEnableVertexAttribArray ( 0 );
    
    
    glBindVertexArray ( 0 );
    

    glBindVertexArray ( VAO );
    glDrawArrays ( GL_TRIANGLES, 0, drawCount );
    
    if ( mesh.type == Polygon ) {
        
        glPolygonMode ( GL_FRONT_AND_BACK, GL_FILL );
        
    } else if ( mesh.type == Line ) {
        
        glPolygonMode ( GL_FRONT_AND_BACK, GL_LINE );
        
    } else if ( mesh.type == Point ) {
        
        glPolygonMode ( GL_FRONT_AND_BACK, GL_POINT );
        
    }
    
    glBindVertexArray ( 0 );
    
    
    glDeleteVertexArrays ( 1, &VAO );
}
